package com.parse.util;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class Binder<T extends Serializable> {
	private static final String TAG = "Binder";
	private Activity activity;
	private Map<String, Method> map = new HashMap<String, Method>();
	private Map<String, View> viewMap = new HashMap<String, View>();

	private T pT;

	/**
	 * 
	 * @author Andy
	 *
	 */
	public class FocusManagerListener implements PropertyChangeListener {

		@Override
		public void propertyChange(PropertyChangeEvent event) {
			String propertyName = event.getPropertyName();

			final View view = viewMap.get(propertyName);
			if (view != null) {

				if (view instanceof EditText) {
					EditText ed = (EditText) view;
					ed.setText(event.getNewValue().toString());
				} else if (view instanceof TextView) {
					TextView ed = (EditText) view;
					ed.setText(event.getNewValue().toString());
				}
			}

			// TODO Auto-generated method stub

		}
	}

	public void init(Activity activity, int[] rs, T obj) {
		this.pT = obj;
		try {
			Method me = this.pT.getClass().getMethod(
					"addPropertyChangeListener", PropertyChangeListener.class);

			me.invoke(this.pT, new FocusManagerListener());

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		this.activity = activity;

		final Method[] methods = this.pT.getClass().getMethods();
		for (Method method : methods) {
			if (method.getName().startsWith("set")) {
				final String name = method.getName().replace("set", "");

				final String fileName = name.substring(0, 1).toLowerCase()
						+ name.substring(1);
				map.put(fileName, method);

			}

		}

		for (int id : rs) {
			final View view = activity.findViewById(id);
			if (view instanceof EditText) {
				EditText ed = (EditText) view;
				final String pTag = ed.getTag().toString();
				ed.addTextChangedListener(new BinderText(pTag));
				viewMap.put(pTag, ed);

			} else if (view instanceof TextView) {

				TextView ed = (TextView) view;
				final String pTag = ed.getTag().toString();
				ed.addTextChangedListener(new BinderText(pTag));
				viewMap.put(pTag, ed);

			}

		}

	}

	private class BinderText implements TextWatcher {

		private String tag;

		public BinderText(String tag) {
			this.tag = tag;
		}

		@Override
		public void afterTextChanged(Editable s) {

			// TODO Auto-generated method stub

		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			try {

				Method m = map.get(tag);
				m.invoke(pT, s.toString());

			} catch (Exception e) {
				Log.v(TAG, "onTextChanged error=" + e);
			}

		}
	}

	public Activity getActivity() {
		return activity;
	}

	public void setActivity(Activity activity) {
		this.activity = activity;
	}

}
